package top.iszsq.config;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import top.iszsq.config.convert.DateTimeConverter;
import top.iszsq.config.convert.DateTimeToStringConverter;
import top.iszsq.config.format.DateTimeSerializer;
import top.iszsq.config.format.DatetimeDeserializer;
import top.iszsq.interceptor.AuthInterceptor;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.TimeZone;

/**
 * web mvc 配置
 * @author zsq
 * @date 2022/2/10 - 21:28
 */
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {

    public static final Logger logger = LoggerFactory.getLogger(MyWebMvcConfig.class);

    @Resource
    private AuthInterceptor authInterceptor;

    /** 是否开启跨域 **/
    @Value("${app.enableCors:false}")
    private boolean enableCors;

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 登录、鉴权拦截器
        InterceptorRegistration authReg = registry.addInterceptor(authInterceptor);
        commonPathPatterns(authReg);

    }

    /**
     * 拦截器公共拦截路径、忽略路径
     * @param itcReg
     */
    private void commonPathPatterns(InterceptorRegistration itcReg){
        itcReg.addPathPatterns("/**");
        itcReg.excludePathPatterns("/swagger-ui.html");
        itcReg.excludePathPatterns("/webjars/**");
        itcReg.excludePathPatterns("/swagger-resources/**");
        itcReg.excludePathPatterns("/error/**");
        itcReg.excludePathPatterns("/doc.html");

        /**magic api 的api由框架自行校验**/
        itcReg.excludePathPatterns("/v2/api-docs/**");
        itcReg.excludePathPatterns("/sqApi/**");
        itcReg.excludePathPatterns("/magic/**");
        itcReg.excludePathPatterns("/_magic-api-sync");
    }

    /**
     * 配置跨域
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        if (enableCors) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowCredentials(true)
                    .allowedMethods("GET", "POST", "DELETE", "PUT","PATCH")
                    .maxAge(3600);
        }
    }

    /**
     * http数据转换器
     * @param converters
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (int i = 0; i < converters.size(); i++) {
            HttpMessageConverter<?> converter = converters.get(i);
            logger.debug("转换器：{}", converter.getClass());

            if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter castConverter = ((MappingJackson2HttpMessageConverter) converters.get(i));
                logger.debug("Jackson转换 MappingJackson2HttpMessageConverter：{}", converter.getClass());

                JavaTimeModule module = new JavaTimeModule();
                //注册model,用于实现jackson joda time序列化和反序列化
                module.addSerializer(LocalDateTime.class, new DateTimeSerializer());
                module.addDeserializer(LocalDateTime.class, new DatetimeDeserializer());

                ObjectMapper om = Jackson2ObjectMapperBuilder.json()
                        .modules(module)
                        .timeZone(TimeZone.getTimeZone("Asia/Shanghai"))
                        .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                        .build();
                // 忽略空bean转json的错误
                om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
                // 统一日期格式
                om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                // 忽略在json字符串中存在, 但在java对象中不存在对应属性的情况, 防止错误
                om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

                castConverter.setObjectMapper(om);
            }
        }

    }

    @Override
    public void addFormatters(FormatterRegistry registry) {

        //日期LocalDateTime转换
        registry.addConverter(new DateTimeConverter());
        registry.addConverter(new DateTimeToStringConverter());
    }

}
